/**
* An object representing the information stored in a component's component.xml file.
*/
jsx3.lang.Class.defineClass("ux.core.util.component.ComponentConfig",
        jsx3.lang.Object,
        null,
        function(config) {

            /**
            * The schema version of the config
            * @private
            */
            config.prototype.schemaVersion = null;

            /**
             * The weight of the component (for ordering of plugins)
             * @private
             */
            config.prototype.weight = null;

            /**
             * The user-readable display name of the component
             * @private
             */
            config.prototype.displayName = null;

            /**
             * The user-readable description name of the component
             * @private
             */
            config.prototype.description = null;

            /**
             * The {ux.core.util.component.Resources} object containing the non-ui resources of the component
             * @private
             */
            config.prototype.resources = null;

            /**
             * The {ux.core.util.component.PluginInterfaces} object containing the list of pluugin interfaces
             * declared and/or implemented by the component
             * @private
             */
            config.prototype.interfaces = null;

            /**
             * The {ux.core.util.component.Messaging} object containing the declarations of messages published
             * and/or subscribed to by the component
             * @private
             */
            config.prototype.messaging = null;

            /**
             * The contextRoot of the component
             * @private
             */
            config.prototype.contextRoot = null;

            /**
            * The constructor for the ComponentConfig class.
            *
            * @param doc {jsx3.xml.Document} the xml document with the component's component.xml content
            *
            * @throws {ux.core.exception.InvalidComponentSchemaException} if the component.xml is not valid
            */
            config.prototype.init = function(doc) {
                this.jsxsuper();
                var children = null;
                try {
                    children = doc.getRootNode().getChildNodes().iterator();
                }
                catch(ex) {
                    throw jsx3.NativeError.wrap(ex);
                }
                while(children.hasNext()) {
                    var child = children.next();
                    var childName = child.getNodeName();
                    if(childName == "schema_version") {
                        this.schemaVersion = child.getValue();
                    }
                    else if(childName == "weight") {
                        try {
                           this.weight = parseInt(child.getValue());
                        }
                        catch(ex) {
                            throw new ux.core.exception.InvalidComponentSchemaException("Child tag 'weight' of the root tag of the component schema is not an integer value.")
                        }
                    }
                    else if(childName == "description") {
                        this.description = child.getValue();
                    }
                    else if(childName == "display_name") {
                        this.displayName = child.getValue();
                    }
                    else if(childName == "resources") {
                        this.resources = new ux.core.util.component.Resources(child);
                    }
                    else if(childName == "interfaces") {
                        this.interfaces = new ux.core.util.component.PluginInterfaces(child);
                    }
                    else if(childName == "messaging") {
                        this.messaging = new ux.core.util.component.Messaging(child);
                    }
                    else {
                        throw new ux.core.exception.InvalidComponentSchemaException("Unknown tag '" + childName + "' in the root tag of the component schema.  Supported tags are: schema_version, weight, description, display_name, resources, interfaces, messaging");
                    }
                }
                if(!this.schemaVersion) {
                    throw new ux.core.exception.InvalidComponentSchemaException("Tag 'schema_version' is a required child of the root tag of the component schema.")
                }
                if(jsx3.util.strTrim(this.schemaVersion.trim()) == "") {
                    throw new ux.core.exception.InvalidComponentSchemaException("Tag 'schema_version' may not be empty.")
                }
                if(!this.description) {
                    throw new ux.core.exception.InvalidComponentSchemaException("Tag 'description' is a required child of the root tag of the component schema.")
                }
                if(jsx3.util.strTrim(this.description.trim()) == "") {
                    throw new ux.core.exception.InvalidComponentSchemaException("Tag 'description' may not be empty.")
                }
                if(!this.displayName) {
                    throw new ux.core.exception.InvalidComponentSchemaException("Tag 'displayName' is a required child of the root tag of the component schema.")
                }
                if(jsx3.util.strTrim(this.displayName.trim()) == "") {
                    throw new ux.core.exception.InvalidComponentSchemaException("Tag 'displayName' may not be empty.")
                }
                if(!this.resources) {
                    throw new ux.core.exception.InvalidComponentSchemaException("Tag 'resources' is a required child of the root tag of the component schema.")
                }
                // check for required values now
            }

            /**
            * Gets the path (relative to, but not including, the contextRoot of the plugin) to a declared class for this
            * component
            *
            * @param str {String} the class name to retrieve the path for
            *
            * @return {String} the path to the javascript file containing the class definition
            */
            config.prototype.getPathToClass = function(str) {
                var iter = this.getResources().getOtherResources();
                while(iter.hasNext()) {
                    var resource = iter.next();
                    if(resource.getType() == "script") {
                        var className = resource.getClassName();
                        if(className == str) {
                            return resource.getPath();
                        }
                    }
                }
                return null;
            }

            /**
            * Sets the contextRoot for the component
            *
            * @param root {String} the contextRoot to set for the component
            */
            config.prototype.setContextRoot = function(root) {
                this.contextRoot = root;
            }

            /**
            * Gets the component's contextRoot
            *
            * @return {String} the component's contextRoot
            */
            config.prototype.getContextRoot = function() {
                return this.contextRoot;
            }

            /**
            * Returns the schema version of the parsed xml document.
            *
            * @return {String} the schema version of the parsed xml document
            */
            config.prototype.getSchemaVersion = function() {
                return this.schemaVersion;
            }

            /**
            * Returns the weight (relative positioning in a multi-child plugin container) of this plugin component.
            *
            * @return {int} the weight of this plugin component
            */
            config.prototype.getWeight = function() {
                return this.weight;
            }

            /**
            * Returns the description of this plugin component
            *
            * @return {String} the description of this plugin component
            */
            config.prototype.getDescription = function() {
                return this.description;
            }

            /**
            * Returns the user-readable display name for this plugin component
            *
            * @return {String} the display name of this plugin component
            */
            config.prototype.getDisplayName = function() {
                return this.displayName;
            }

            /**
            * Returns the Resources object for this plugin component
            *
            * @return {ux.core.util.component.Resources} the Resources object for this plugin component
            */
            config.prototype.getResources = function() {
                return this.resources;
            }

            /**
            * Returns the PluginInterfaces object for this plugin component
            *
            * @return {ux.core.util.component.PluginInterfaces} the PluginInterfaces object for this plugin component
            */
            config.prototype.getPluginInterfaces = function() {
                return this.interfaces;
            }

            /**
            * Returns the Messaging obejct for this plugin component
            *
            * @return {ux.core.util.component.Messaging} the Messaging object for this plugin component
            */
            config.prototype.getMessagingConfig = function() {
                return this.messaging;
            }

            /**
            * Returns a string representing this object in the xml format specified by the component.xsd schema.  This
            * string should be an exact duplicate of the original component.xml in the sense that passing a document
            * with it's content to the contructor of this class would return an equivalent instance of this class to
            * this one.
            *
            * @param prepend {String} a string to be prepended to each line of the returned XML (useful for indenting)
            *
            * @returns {String} this ComponentConfig as XML, as specified by the component.xsd schema
            */
            config.prototype.toString = function(prepend) {
                if(!prepend) {
                    prepend = "";
                }
                ret = prepend + "<component>\n";
                if(this.schemaVersion) {
                    ret += prepend + "   <schema_version>" + this.schemaVersion + "</schemaVersion>\n";
                }
                if(this.description) {
                    ret += prepend + "   <description>" + this.description + "</description>\n";
                }
                if(this.displayName) {
                    ret += prepend + "   <display_name>" + this.displayName + "</display_name>\n";
                }
                if(this.weight) {
                    ret += prepend + "   <weight>" + this.weight + "</weight>\n";
                }
                if(this.resources) {
                    ret += this.resources.toString(prepend + "   ");
                }
                if(this.interfaces) {
                    ret += this.interfaces.toString(prepend + "   ");
                }
                if(this.messaging) {
                    ret += this.messaging.toString(prepend + "   ");
                }
                ret += prepend + "</component>\n";
                return ret;
            }
        }
);